<template>
    <div class="page">
        <ToolBar
            :options="toolBar"
            :form="state.searchData"
            :initData="state.initData"
            @event="handleEvent">
        </ToolBar>
        <div class="table" v-loading="state.tableData.loading">
            <el-table
                :data="state.tableData.data"
                @selection-change="handleSelectionChange"
                style="width: 100%"
                :height="state.tableHeight">
                <el-table-column v-if="options.config.selection" type="selection" width="42" align="center" fixed/>
                <el-table-column v-if="options.config.expand" type="expand" fixed>
                    <template #default="scope">
                        <slot name="expand" :row="scope.row"></slot>
                    </template>
                </el-table-column>
                <el-table-column
                    v-for="(col, index) in tableColumn"
                    :key="index"
                    :prop="col.key"
                    :align="col.align || ''"
                    :width="col.width"
                    :min-width="col.minWidth"
                    :fixed="col.fixed"
                    :label="col.label">
                    <template v-slot="scope">
                        <template v-if="col.ui">
                            <ZUI :item="col" :form="scope.row" :initData="state.initData" @event="handleEvent"></ZUI>
                        </template>
                        <template v-else-if="col.format">
                            {{ typeof col.format === 'string'
                                ? tableFormat[col.format]({row: scope.row, item: col, initData: state.initData})
                                : col.format({row: scope.row, item: col, initData: state.initData}) }}
                        </template>
                        <template v-else>
                            {{ scope.row[col.key] }}
                        </template>
                    </template>
                </el-table-column>
            </el-table>
        </div>
        <div class="paging" v-if="options.config.paging">
            <Pagination
                type="simple"
                :pageData="state.pageData"
                @change="handleChange">
            </Pagination>
        </div>
        <DialogForm
            v-if="state.dialog.visible"
            :options="state.dialog"
            @closed="dialogFormClosed">
        </DialogForm>
    </div>
</template>

<script lang="ts">
import {
    Action as FormAction, type Fetch, type UIProps,
    type BindProps, type ButtonProps, type Dict, type FormProps,
    type BindOn, type InitData
} from './Form.vue'
import { type Config as DialogConfig } from './DialogForm.vue'
import { UIName } from './UI.vue'
import { type TableFormatKey } from './utils'

export interface Options {
    config: Config
    body: Body
}
interface Config {
    expand?: boolean // 表格展开
    autoInit?: boolean // 自动执行
    heightAuto?: boolean // 高度自适应
    serialization?: boolean // 序列化执行（在异步请求参数时，能保证先后顺序）
    initData?: InitData // 全局数据，支持同步和异步请求
    defaultSearchData?: object // 默认查询参数，仅支持同步数据
    paging?: boolean | Paging // 分页配置
    log?: boolean // 是否打印日志
    selection?: boolean // 是否可勾选数据
    fetch: Fetch // 请求配置
}
interface Body {
    column: Column[] // 列配置
    toolBar?: ToolBarItem[] // 工具栏
}
interface ToolBarItem {
    searchPosition?: string // 搜索位置 left | right
    left?: ToolBarItemUI[]
    right?: ToolBarItemUI[]
}
export enum Action {
    search = 'search', // 搜索
    searchReset = 'searchReset', // 搜索重置
    refresh = 'refresh', // 刷新
    dialogForm = 'dialogForm', // 表单弹窗
    emptyDialogForm = 'emptyDialogForm', // 空白表单弹窗
    fetch = 'fetch', // 发起请求
    confirm = 'confirm', // 确认提示
    formCancel = FormAction.formCancel, // 弹窗表单操作
    formSubmit = FormAction.formSubmit, // 弹窗表单操作
}
interface DialogFormConfig extends Omit<DialogConfig, 'title'>  {
    closed?: DialogFormClosed // 关闭窗口后
}
interface Paging {
    pageSize?: number // 每页条数 默认15条
    totalKey?: string // 默认 'total'
    dataKey?: string // 默认 'list'
}
interface Confirm {
    tipKey?: string
    content: string
    title: string
}
interface DialogFormClosed {
    queryTableData?: boolean // 是否查询表格数据, 默认查询
    toFirstPage?: boolean // 跳转到第一页
}
interface DialogFormOptions {
    config?: DialogFormConfig
    body?: UI[]
}

interface UI extends ButtonProps, BindProps, ActionProps, ButtonGroup, ColumnCommon, FormProps {
    label?: string
    key?: string
    ui: `${UIName}`
    sort?: number // 排序号 从小到大排序
    startPlaceholder?: string
    endPlaceholder?: string
    placeholder?: string
    valueFormat?: string
    render?: (p: any) => any // 使用vue 的h函数渲染组件
}

interface ToolBarItemUI extends UI {
    width?: string
    clearable?: boolean
}

interface ButtonGroupItem extends ButtonProps, BindProps, ActionProps {}
interface ButtonGroup {
    align?: string
    children?: ButtonGroupItem[]
}

// 内置操作
interface ActionProps {
    actionName?: `${Action}`
    confirm?: Confirm
    fetch?: Fetch // 请求配置
    options?: DialogFormOptions
}

interface Column extends ColumnExpand, ButtonGroup {
    label?: string
    key?: string
    width?: string | number
    minWidth?: string | number
    align?: string
    fixed?: string | number | boolean
    on?: BindOn
    [key: string]: any
}
// 表格列扩展
interface ColumnExpand {
    format?: TableFormatKey | ((p: any) => any)
    ui?: `${UIName}`
    render?: (p: any) => any // 使用vue 的h函数渲染组件
    dict?: ColumnDict
    common?: ColumnCommon
    search?: ColumnForm
    form?: ColumnForm
}
interface ColumnCommon {
    dict?: ColumnDict
}
interface ColumnDict extends Omit<Dict, 'data'> {
    data: any[] | ((p: ColumnDictParams) => any)
}
interface ColumnDictParams {
    row: any
    item: any
    initData: InitData
}
interface ColumnForm extends Omit<UIProps, 'dict'>, ColumnCommon {}
</script>

<script setup lang="ts">
import { type PropType } from 'vue'
import Pagination from './Pagination.vue'
import ToolBar from './ToolBar.vue'
import DialogForm from './DialogForm.vue'
import ZUI from './UI.vue'
import { tableFormat } from './utils'
import useTable from './hooks/useTable'

const props = defineProps({
    options: {
        type: Object as PropType<Options>,
        default: () =>({})
    }
})

const {
    state, toolBar, tableColumn,
    handleEvent, handleChange, dialogFormClosed,
    getData, refresh
} = useTable(props)

const handleSelectionChange = (val: any) => {
    state.searchData.selection = val
}

defineExpose({
    getData,
    refresh
})

</script>

<style lang="scss" scoped>
.page{
    --zui-padding: 15px;
    padding: var(--zui-padding);
}

.paging{
    background-color: #fff;
    padding: 10px;
    display: flex;
    justify-content: flex-end;
}
</style>